﻿using StarryEdge.Core.Device;
using StarryEdge.Core.Models.Testers;
using StarryEdge.Core.Models;
using StarryEdge.Core;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace StarryEdge.Devices.MeterDevice.Testers
{
    public class RJ6902CAGX : NormalDeviceBase, IDeviceInteraction<string>
    {
        private byte[] _quyData = new byte[] { 0x7B, 0x00, 0x08, 0x02, 0xF0, 0x5B, 0x55, 0x7D };//查询测试数据
        public RJ6902CAGX(ICommunication com, IStarryEdgeLog edgeLog, Func<DeviceInfoModel, IDevice, bool> func) : base(com, edgeLog, func)
        {
        }

        public void Close() => _com.Close();

        public bool Open() => _com.Open();

        public TValue ReadSingle<TValue>(string address, int length = 3)
        {
            Stopwatch _stopwatch = new Stopwatch();
            List<byte> bytes = new List<byte>();
            for (int i = 0; i < length; i++)
            {
                try
                {
                    _com.Send(_quyData);
                    int resourc_length = 36;
                    Thread.Sleep(10);
                    while (true)
                    {
                        bytes.AddRange(_com.Receive());
                        if (_stopwatch.ElapsedMilliseconds > 500 || bytes.Count == resourc_length)
                        {
                            break;
                        }
                        Thread.Sleep(10);
                    }
                    if (bytes.Count < 9)
                    {
                        throw new Exception("协议通信无响应");
                    }
                    if (ToResult_RJ6902CAGX(bytes.ToArray()) is TValue obj)
                    {
                        return obj;
                    }
                    return default;
                }
                catch (Exception ex)
                {
                    _edgeLog.LogRun($"[{nameof(RJ6902CAGX)}] 异常：{ex}", Core.Enums.LogLevel.Warning);
                    if (_func.Invoke(_com.DeviceInfo, this))
                    {
                        continue;
                    }
                }
            }
            return default;
        }

        private RJ6902CAGXResultModel ToResult_RJ6902CAGX(byte[] bytes)
        {
            if (bytes == null) { return null; }
            if (bytes.Length < 36) { return null; }
            return new RJ6902CAGXResultModel()
            {
                跌落1 = ToUShort(bytes.Skip(6).ToArray()),
                跌落2 = ToUShort(bytes.Skip(8).ToArray()),
                跌落3 = ToUShort(bytes.Skip(10).ToArray()),
                VP电压 = ToUShort(bytes.Skip(12).ToArray()),
                升压时间 = ToUShort(bytes.Skip(14).ToArray()),
                电阻测试数据 = ToInt(bytes.Skip(16).ToArray()) / 10.0F,
                电容测试数据 = ToUShort(bytes.Skip(20).ToArray()),
                开路结果 = bytes[22],
                放电1结果 = bytes[23],
                VP结果 = bytes[24],
                放电2结果 = bytes[25],
                跌落1结果 = bytes[26],
                跌落2结果 = bytes[27],
                跌落3结果 = bytes[28],
                TL结果 = bytes[29],
                TH结果 = bytes[30],
                电阻测试结果 = bytes[31],
                电容测试结果 = bytes[32],
                总结果 = bytes[33],
                TestMsg = BitConverter.ToString(bytes)
            };
        }

        private int ToInt(byte[] bytes) => (int)((bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]);
        private ushort ToUShort(byte[] bytes) => (ushort)((bytes[0] << 8) | bytes[1]);

        public bool WriteSingle(string address, object value, int length)
        {
            byte[] bytes = Encoding.ASCII.GetBytes(address);
            for (int i = 0; i < length; i++)
            {
                try
                {
                    _com.Send(bytes);
                    return true;
                }
                catch (Exception ex)
                {
                    _edgeLog.LogRun($"[{nameof(RJ6902CAGX)}] 异常：{ex}", Core.Enums.LogLevel.Warning);
                    if (_func.Invoke(_com.DeviceInfo, this))
                    {
                        return default;
                    }
                }
            }
            return false;
        }
    }
}
